#include "CIrrDeviceLinux.h"
#include <Keycodes.h>
#include <IEventReceiver.h>
#include "EventSender_3dijoy_Linux.h"
#include "./Input3dijoy/include/Kbhit.h"
#include <unistd.h>

const int KEY_LIM_S = BUTTON_RIGHT - BUTTON_UP + 1;
const int KEY_OFFSET_BASE = BUTTON_UP;
static irr::EKEY_CODE axis2key[KEY_LIM_S]={irr::KEY_UP,irr::KEY_DOWN,irr::KEY_LEFT,irr::KEY_RIGHT};

bool EventSender_3dijoy_Linux::Init(irr::CIrrDeviceStub* dev, int w, int h)
{
  this->dev = dev;
  displayW = w;
  displayH = h;

  DeviceInit();
  BOOL ready = BluetoothDongleReady();
  usleep(3000);
  if(ready == FALSE)
    return false;

  //MessageBox(0, "For Connect 3dijoy control", "PTR", MB_OK); //<
  printf("Press a key for connecting 3dijoy Controller!\n");
  getchar();
  printf("Starting...\n");

  for(int i=0; i<4; ++i)
  {
    JoyDevice jDev;
    if( SearchDevice(&jDev.deviceId,&jDev.deviceInfo) == TRUE )
    {
      devices.push_back(jDev);
      printf(" searching a device!\n");
      if(devices.size()==1)
        break;
    }
    else
    {
      continue;
    }
  }


  if(devices.empty())
    return false;

#define BIT_ACC 0x01
#define BIT_DESKTOP_MOUSE 0x02
#define BIT_AXIS 0x04

  for(int i=0; i<devices.size(); ++i)
  {
    UINT8& id = devices[i].deviceId;
    if( CreateConnection(id) == TRUE )
    { // success
      printf("Created connction to 3dijoy.\n");
      //SetOutputMode(id, BIT_ACC, TRUE);
      //SetOutputMode(id, BIT_DESKTOP_MOUSE, TRUE);
      //SetOutputMode(id, BIT_AXIS, TRUE);
    }
  }


  return true;
}

void EventSender_3dijoy_Linux::Term()
{
  for(int i=0; i<devices.size(); ++i)
  {
    UINT8& id = devices[i].deviceId;
    ReleaseConnection(id);
  }
}

void EventSender_3dijoy_Linux::_OccurAnAxisEvent(UINT16 keyCode, bool pressed)
{
  irr::SEvent event;
  event.EventType = irr::EET_KEY_INPUT_EVENT;
  event.KeyInput.Key = axis2key[keyCode - KEY_OFFSET_BASE];
  event.KeyInput.PressedDown = pressed;
/*
  WORD KeyAsc=0;
  GetKeyboardState(allKeys);
  ToAscii(event.KeyInput.Key,0,allKeys,&KeyAsc,0);
  event.KeyInput.Char = (KeyAsc & 0x00ff); //KeyAsc >= 0 ? KeyAsc : 0;
//*/

  irr::CIrrDeviceLinux* dev_ = static_cast<irr::CIrrDeviceLinux*>(dev);
  if(dev_)
    dev_->postEventFromUser(event);
}

int EventSender_3dijoy_Linux::_GetPos_RelX()
{
  static const int offsetX = displayW/2;
  return data.Mpos.RelPosX + offsetX;
}

int EventSender_3dijoy_Linux::_GetPos_RelY()
{
  static const int offsetY = displayH/2;
  return data.Mpos.RelPosY + offsetY;
}

void EventSender_3dijoy_Linux::_OccurAnMouseEvent()
{
  static const int offsetX = displayW/2;
  static const int offsetY = displayH/2;

  for(int i=0; i<devices.size(); ++i)
  {
    UINT8& id = devices[i].deviceId;

    if(CheckJoy(id))
      ReadRemoteDeviceData(id, &data);
  }


  irr::SEvent event;
	event.EventType = irr::EET_MOUSE_INPUT_EVENT;
	event.MouseInput.Event = irr::EMIE_MOUSE_MOVED;

  static int oldRelX=data.Mpos.RelPosX, oldRelY=data.Mpos.RelPosY;
  printf("raw: data.Mpos.(%d, %d)\n", data.Mpos.RelPosX, data.Mpos.RelPosY);

  int movedX = data.Mpos.RelPosX - oldRelX;
  if( movedX != 0 )
  { // moved
    event.MouseInput.X = movedX + offsetX;
  }else{
    event.MouseInput.X = offsetX;
  }

  int movedY = data.Mpos.RelPosY - oldRelY;
  if( movedY != 0 )
  { // moved
    event.MouseInput.Y = movedY + offsetY;
  }else{
    event.MouseInput.Y = offsetY;
  }

  irr::CIrrDeviceLinux* dev_ = static_cast<irr::CIrrDeviceLinux*>(dev);
  if(dev_)
  {
    //printf("(%d, %d)\n", event.MouseInput.X, event.MouseInput.Y);
    dev_->postEventFromUser(event);
  }
}

static unsigned callCnt=0;

void EventSender_3dijoy_Linux::PostEvent2Irr()
{
  //printf("PostEvent2Irr (%d) ", callCnt++);

  for(int i=0; i<devices.size(); ++i)
  {
    UINT8& id = devices[i].deviceId;

    if(CheckJoy(id))
      ReadRemoteDeviceData(id, &data);
  }

  if(data.Buttons[BUTTON_LEFT] == TRUE)
    _OccurAnAxisEvent(BUTTON_LEFT, true);
  else
    _OccurAnAxisEvent(BUTTON_LEFT, false);

  if(data.Buttons[BUTTON_UP] == TRUE)
    _OccurAnAxisEvent(BUTTON_UP, true);
  else
    _OccurAnAxisEvent(BUTTON_UP, false);

  if(data.Buttons[BUTTON_RIGHT] == TRUE)
    _OccurAnAxisEvent(BUTTON_RIGHT, true);
  else
    _OccurAnAxisEvent(BUTTON_RIGHT, false);

  if(data.Buttons[BUTTON_DOWN] == TRUE)
    _OccurAnAxisEvent(BUTTON_DOWN, true);
  else
    _OccurAnAxisEvent(BUTTON_DOWN, false);


  _OccurAnMouseEvent();
}
